This is a MODIFIED version of FreeJ2ME-Plus, not the upstream release.

Modified by: NSO Classic
Modified on: 2026-09-16
Base:        FreeJ2ME-Plus 1.52, https://github.com/TASEmulators/freej2me-plus
Released as: freej2me-plus 1.52-nso.24
Source:      https://cdn.nsoclassic.xyz/tools/freej2me-plus/1.52-nso.24/freej2me-plus-1.52-nso.24-source.tar.gz

             The URL is pinned to this release on purpose. GPLv3 section 6
             wants the source that corresponds to the binary you received, and
             a link to the current download page stops being that the moment a
             newer build becomes current. Pinning costs a commit before every
             republish; the alternative silently expires the source offer.

Changes against upstream 1.52 (Changes in 1.52-nso.10):

  * Multi-OS Desktop Packaging:
    - Added native macOS App Bundle (NSO Classic.app) scaffolding and packaging scripts.
      Routes application state/RMS directly to ~/Library/Application Support/NSO Classic.
    - Added Win32 native wWinMain C stub launcher (nso-classic.exe) hiding console window
      and routing state to %LOCALAPPDATA%\NSO Classic with Unicode path handling.
    - Bundled Eclipse Temurin OpenJDK 17.0.14+7 JRE into portable zip releases.
    - Added automatic canvas focus (lcd.requestFocusInWindow) upon window creation.


  * The AWT runner advertises a physical keyboard through the private property
    `freej2me.keyboard=qwerty` instead of overwriting `microedition.platform`,
    which is the emulator's identity and is read by MIDlets for capability
    decisions. Without this, a typed `2` reached the MIDlet as multi-tap `a`.

  * `Display.postInputEvent` no longer spawns a thread per event. Input events
    go through the serial queue, so back-to-back keyTyped/keyPressed pairs can
    no longer be delivered out of order.

  * `MobilePlatform.keyPressed` routes the CLR keycode to a focused lcdui text
    editor as backspace, so Backspace reaches an lcdui text field.

  * `Connector.open("socket://host:port")` returns a real TCP socket. Upstream
    fell through to its HTTP implementation, so a MIDlet that cast the result
    to `SocketConnection` -- the only thing the CLDC contract allows -- died
    with a ClassCastException before sending a byte. No online game could
    connect. `openInputStream`/`openDataInputStream` on a `socket://` URL now
    own the connection, as CLDC requires: closing that stream closes the
    socket.

  * Each keystroke is delivered to the screen that was current when it
    arrived. `MobilePlatform` held the receiver in one shared static field
    that every later input event overwrote, while the queued event only read
    it when the event thread ran, so a character typed just before a screen
    change landed on the replacement screen -- on the game's login and
    registration forms that meant a password fragment, and a Backspace,
    reaching the wrong screen.

  * The editable field row is drawn once, by a shared painter. `TextBox` (a
    Screen) and `TextField` (an Item) each carried their own byte-identical
    copy of it, so every rule about what an editor may show had to be written
    twice and kept in step. It was not: a `PASSWORD` field drew the credential
    in clear text for as long as the screen was up, and the keypad character
    picker's candidate was drawn at the caret before the picker had been used,
    so a typed character was displayed with an extra one after it.

  * Enter commits an editor instead of inserting a character, on both editor
    paths. The AWT runner maps Enter to FIRE, and FIRE means "insert the
    picked keypad candidate"; on a PC keyboard there is no candidate to
    insert, so the key did nothing and the field could not be left without the
    mouse. FIRE now inserts only while the picker is actually in use. On a
    `TextBox` it otherwise runs the screen's first command; on a `TextField`,
    which is the editor the game's login form is built from, it runs the
    field's own command, or the screen's first command if the field has none.
    1.52-nso.6 carried this for `TextBox` only, so the login form it shipped
    with still appended a character on Enter.

  * A press on the command bar the native screens draw runs the command under
    the pointer. The bar was drawn but never hit-tested, so on a touch build
    the visible OK and Cancel did nothing. A focused item's own command is
    drawn centred between them and is hit-tested there; 1.52-nso.6 read that
    press as the screen command whose half it fell in.

  * A `Form` item's default command runs at all. `Displayable.render` drew the
    label and `Form.getItemCommand` returned the command, but nothing ever
    called its listener, so on the game's login form the drawn command was
    decoration on every input path.

  * The native screen chrome is a two-tone monochrome sheet - paper, ink, one
    rule - with the caret, the keypad candidate and the charset hint each
    given their own colour, so what the field is doing is legible instead of
    inferred from position.

Distributed under the GPLv3, as upstream is. See LICENSE.

This notice is required by GPLv3 section 5(a) and ships in both the binary
archive and the corresponding source tarball.
